// Copyright 2012 Sergio, Raul, Dorival. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#ifndef GEMLAB_CYLINDER_H
#define GEMLAB_CYLINDER_H

// Std lib
#include <cmath>

// MechSys
#include <mechsys/dem/torus.h>

namespace GemLab
{

class Cylinder
{
public:
    // Constructor
    Cylinder (Torus * T0, Torus * T1, Vec3_t const * Y0, Vec3_t const * Y1);  ///< Initial T0 and final T1 tori
    Cylinder (Torus & T0, Torus & T1, Vec3_t const & Y0, Vec3_t const & Y1);  ///< Initial T0 and final T1 tori

    // Methods
    void UpdatedL ();                                                                                     ///< UdatedL for the tori and cylinder
    void Draw      (std::ostream & os, double Radius=1.0, char const * Color="Blue", bool BPY=false);

    // Data
    Torus       * T0; ///< First torus
    Torus       * T1; ///< Second torus
    Vec3_t const *Y0; ///< Lower point of the first torus
    Vec3_t const *Y1; ///< Lower point of the first torus
    Vec3_t        X0; ///< Center of the first  torus
    Vec3_t        X1; ///< Center of the second torus
    double      Dmax;
};


/////////////////////////////////////////////////////////////////////////////////////////// Implementation /////


inline Cylinder::Cylinder (Torus * TheT0, Torus * TheT1, Vec3_t const * TheY0, Vec3_t const * TheY1)
    : T0(TheT0), T1(TheT1)
{
    X0 = *T0->X0;
    X1 = *T1->X0;
    Y0 = TheY0;
    Y1 = TheY1;
    T0->X0 = &X0;
    T1->X0 = &X1;
    Dmax = sqrt(0.25*dot(X0 - X1,X0 - X1) + pow(std::max(T0->R,T1->R),2));
}

inline Cylinder::Cylinder (Torus & TheT0, Torus & TheT1, Vec3_t const & TheY0, Vec3_t const & TheY1)
    : T0(&TheT0), T1(&TheT1)
{
    X0 = *T0->X0;
    X1 = *T1->X0;
    Y0 = &TheY0;
    Y1 = &TheY1;
    T0->X0 = &X0;
    T1->X0 = &X1;
    Dmax = sqrt(0.25*dot(X0 - X1,X0 - X1) + pow(std::max(T0->R,T1->R),2));
}

inline void Cylinder::UpdatedL ()
{
    X0 = 0.5*(*T0->X1 + *Y0);
    X1 = 0.5*(*T1->X1 + *Y1);
}

inline void Cylinder::Draw (std::ostream & os, double Radius, char const * Color, bool BPY)
{
    if (BPY)
    {
        //throw new Fatal("Cylinder shape not implemented for blender");
    }
    else
    {
        double R0 = norm((*T0->X0)-(*T0->X1));
        double R1 = norm((*T1->X0)-(*T1->X1));
        os << "cone { \n <" << (*T0->X0)(0) << "," << (*T0->X0)(1) << "," << (*T0->X0)(2) << "> , " << R0 + Radius << "\n"
                     << "<" << (*T1->X0)(0) << "," << (*T1->X0)(1) << "," << (*T1->X0)(2) << "> , " << R1 + Radius << "\n"
                            << " pigment { color " << Color        <<" } }\n"
           << "cone { \n <" << (*T0->X0)(0) << "," << (*T0->X0)(1) << "," << (*T0->X0)(2) << "> , " << R0 - Radius << "\n"
                     << "<" << (*T1->X0)(0) << "," << (*T1->X0)(1) << "," << (*T1->X0)(2) << "> , " << R1 - Radius << "\n"
                            << " pigment { color " << Color        <<" } }\n";
    }
}

}; // namespace GemLab

#endif // GEMLAB_CYLINDER_H
